package com.liuyi.usercenterservice.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liuyi.usercenterservice.common.BaseResponse;
import com.liuyi.usercenterservice.common.ErrorCode;
import com.liuyi.usercenterservice.entity.domain.Team;
import com.liuyi.usercenterservice.entity.domain.User;
import com.liuyi.usercenterservice.entity.domain.UserTeam;
import com.liuyi.usercenterservice.entity.enums.TeamStatusEnum;
import com.liuyi.usercenterservice.entity.request.TeamJoinRequest;
import com.liuyi.usercenterservice.entity.request.TeamQueryRequest;
import com.liuyi.usercenterservice.entity.request.TeamQuitRequest;
import com.liuyi.usercenterservice.entity.request.TeamUpdateRequest;
import com.liuyi.usercenterservice.entity.vo.TeamVO;
import com.liuyi.usercenterservice.exception.BusinessException;
import com.liuyi.usercenterservice.mapper.TeamMapper;
import com.liuyi.usercenterservice.service.TeamService;
import com.liuyi.usercenterservice.service.UserService;
import com.liuyi.usercenterservice.service.UserTeamService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
* @author admin
* @description 针对表【team(队伍)】的数据库操作Service实现
* @createDate 2024-07-01 21:08:36
*/
@Service
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team> implements TeamService {
    @Resource
    UserService userService;
    @Resource
    UserTeamService userTeamService;
    @Resource
    TeamMapper teamMapper;
    @Transactional
    @Override
    public Long addTeam(Team team, User loginUser) {
        //1. 请求参数是否为空？
        if (team == null){
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        //2. 是否登录，未登录不允许创建
        if (loginUser == null){
            throw new BusinessException(ErrorCode.NOT_LOGIN);
        }
        //region 3.校验信息

        //        a. 队伍人数 > 1 且 <= 20
        Integer maxNum = team.getMaxNum();
        if (maxNum <= 1 || maxNum > 20){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍人数 > 1 且 <= 20");
        }
        //        b. 队伍标题 <= 20
        String teamName = team.getName();
        if (StringUtils.isNotBlank(teamName) && teamName.length() > 20){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍标题 <= 20");
        }
        //        c. 描述 <= 512
        String teamDesc = team.getDescription();
        if (StringUtils.isNotBlank(teamDesc) && teamDesc.length() > 512){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"描述 <= 512");
        }
        //        d. status 是否公开（int）不传默认为 0（公开）
        TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByValue(Optional.ofNullable(team.getStatus()).orElse(0));
        if (statusEnum == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍状态不满足要求");
        }
        //        e. 如果 status 是加密状态，一定要有密码，且密码 <= 32
        String password = team.getPassword();
        if (TeamStatusEnum.SECRET.equals(statusEnum)){
            if (StringUtils.isBlank(password) || password.length() > 32){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"加密状态，一定要有密码，且密码长度小于32");
            }
        }
        team.setStatus(statusEnum.getValue());
        // f. 超时时间 > 当前时间
        Date expireTime = team.getExpireTime();
        Date now = new Date();
        if (expireTime != null && now.after(expireTime)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"超时时间 > 当前时间");
        }
        Long userId = loginUser.getId();
        //g. 校验用户最多创建 5 个队伍
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        int count = count(queryWrapper);
        if (count >= 5){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户最多创建5个队伍");
        }
        //endregion
        //        4. 插入队伍信息到队伍表
        team.setId(null);
        team.setUserId(userId);
        team.setCreateTime(now);
        boolean saveTeam = save(team);
        Long teamId = team.getId();
        if (!saveTeam){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "创建队伍失败");
        }
        //5. 插入用户 => 队伍关系到关系表
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(userId);
        userTeam.setCreateTime(now);
        userTeam.setJoinTime(now);
        userTeam.setTeamId(teamId);
        boolean saveUserTeam = userTeamService.save(userTeam);
        if (!saveUserTeam){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "创建队伍失败");
        }
        return teamId;
    }

    @Override
    public List<TeamVO> listTeam(TeamQueryRequest queryRequest, boolean isAdmin) {
        // 只有管理员才能查看加密还有非公开的房间
        if (!isAdmin){
            TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByValue(queryRequest.getStatus());
            if (statusEnum != null && !statusEnum.equals(TeamStatusEnum.PUBLIC)){
                throw new BusinessException(ErrorCode.NO_AUTH,"无权限");
            }
            queryRequest.setStatus(0);
        }
        //5. 关联查询已加入队伍的用户信息
        List<TeamVO> teamInfo = teamMapper.getTeamInfo(queryRequest);
        teamInfo.forEach(teamVO -> {
            int size = teamVO.getUsers().size();
            teamVO.setHasJoinNum(size);
            teamVO.setHasJoin( size > 1);
        });
        return teamInfo;
    }

    @Override
    public boolean updateTeam(TeamUpdateRequest teamRequest, User loginUser) {
        if (loginUser == null){
            throw new BusinessException(ErrorCode.NOT_LOGIN,"请先登录！");
        }
        //1. 判断请求参数是否为空
        Long teamId = teamRequest.getId();
        if (teamId == null || teamId < 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍Id错误");
        }
        //2. 查询队伍是否存在
        Team oldTeam = getById(teamId);
        if (oldTeam == null){
            throw new BusinessException(ErrorCode.NOT_EXIST_DATA,"该队伍不存在");
        }
        Long userId = loginUser.getId();
        //3. 只有管理员或者队伍的创建者可以修改
        if (!userService.isAdmin(loginUser) && userId.equals(oldTeam.getUserId())){
            throw new BusinessException(ErrorCode.NO_AUTH,"无权限修改");
        }
        //4. 如果用户传入的新值和老值一致，就不用 update 了（可自行实现，降低数据库使用次数）TODO
        TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(teamRequest.getStatus());
        if (teamStatusEnum != null){
            //如果修改状态为公开或私密则密码清空
            if (TeamStatusEnum.PUBLIC.equals(teamStatusEnum) || TeamStatusEnum.PRIVATE.equals(teamStatusEnum)){
                teamRequest.setPassword("");
            }
            //5. 如果队伍状态改为加密，必须要有密码
            String password = teamRequest.getPassword();
            if (TeamStatusEnum.SECRET.equals(teamStatusEnum) && StringUtils.isBlank(password)){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍更改为加密必须有密码");
            }
        }
        Integer maxNum = teamRequest.getMaxNum();
        if (maxNum != null && (maxNum < 2  || maxNum > 20)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍人数 > 1 且 <= 20");
        }
        Team team = new Team();
        BeanUtils.copyProperties(teamRequest,team);
        //6. 更新成功
        return updateById(team);
    }

    @Override
    public Boolean joinTeam(TeamJoinRequest joinRequest, User loginUser) {
        if (loginUser == null){
            throw new BusinessException(ErrorCode.NOT_LOGIN,"请先登录！");
        }
        Long teamId = joinRequest.getTeamId();
        if (teamId == null || teamId <= 0){
            throw  new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //队伍必须存在
        Team team = getById(teamId);
        if (team == null){
            throw new BusinessException(ErrorCode.NOT_EXIST_DATA,"队伍不存在");
        }
        //未过期的队伍
        Date now = new Date();
        if (now.after(team.getExpireTime())){
            throw new BusinessException(ErrorCode.DATA_ERROR,"该队伍已过期");
        }
        //禁止加入私有的队伍
        TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByValue(team.getStatus());
        if (TeamStatusEnum.PRIVATE.equals(statusEnum)){
            throw new BusinessException(ErrorCode.DATA_ERROR,"禁止加入私有的队伍");
        }
        //如果加入的队伍是加密的，必须密码匹配才可以
        String password = joinRequest.getPassword();
        if (TeamStatusEnum.SECRET.equals(statusEnum)){
            if (StringUtils.isBlank(password)){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"加入加密的队伍必须有密码");
            }
            if (!password.equals(team.getPassword())){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码错误");
            }

        }
        //用户最多加入 5 个队伍
        Long userId = loginUser.getId();
        List<UserTeam> userTeams = userTeamService.list(new QueryWrapper<UserTeam>().eq("user_id", userId));
        if (userTeams.size() >= 5){
            throw new BusinessException(ErrorCode.DATA_ERROR,"用户最多加入 5 个队伍");
        }
        //不能加入自己的队伍，不能重复加入已加入的队伍（幂等性）
        for (UserTeam userTeam : userTeams) {
            if (teamId.equals(userTeam.getTeamId())){
                throw new BusinessException(ErrorCode.DATA_ERROR,"不能重复加入已加入的队伍");
            }
        }
        //只能加入未满
        Integer maxNum = team.getMaxNum();
        int userCount= userTeamService.count(new QueryWrapper<UserTeam>().eq("team_id", teamId));
        if (userCount >= maxNum){
            throw new BusinessException(ErrorCode.DATA_ERROR,"队伍人数已满");
        }
        //新增队伍 - 用户关联信息
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(userId);
        userTeam.setTeamId(teamId);
        userTeam.setJoinTime(now);
        return userTeamService.save(userTeam);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean quitTeam(TeamQuitRequest quitRequest, User loginUser) {
        if (loginUser == null){
            throw new BusinessException(ErrorCode.NOT_LOGIN,"请先登录！");
        }
        Long teamId = quitRequest.getTeamId();
        if (teamId == null || teamId <= 0){
            throw  new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //队伍必须存在
        Team team = getById(teamId);
        if (team == null){
            throw new BusinessException(ErrorCode.NOT_EXIST_DATA,"队伍不存在");
        }
        //校验是否已加入队伍
        Long userId = loginUser.getId();
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("team_id",teamId).eq("user_id",userId);
        UserTeam userTeam = userTeamService.getOne(queryWrapper);
        if (userTeam == null){
            throw new BusinessException(ErrorCode.DATA_ERROR,"用户还没加入队伍");
        }
        queryWrapper = new QueryWrapper<UserTeam>().eq("team_id", teamId);
        int count = userTeamService.count(queryWrapper);
        //只剩一人，队伍解散
        if (count <= 1){
            removeById(teamId);
        }else {
            //如果是队长退出队伍，权限转移
            if (team.getUserId().equals(userId)){
                queryWrapper = new QueryWrapper<UserTeam>().eq("team_id",teamId);
                queryWrapper.orderByAsc("id");
                List<UserTeam> userTeams = userTeamService.page(new Page<UserTeam>(0, 2),queryWrapper).getRecords();
                if (userTeams == null || userTeams.size() <= 1){
                    throw new BusinessException(ErrorCode.DATA_ERROR,"更新队伍队长失败");
                }
                UserTeam newUser = userTeams.get(1);
                team.setUserId(newUser.getUserId());
                if (!updateById(team)){
                    throw new BusinessException(ErrorCode.SYSTEM_ERROR,"更新队伍队长失败");
                }
            }
        }
        queryWrapper = new QueryWrapper<UserTeam>().eq("team_id", teamId).eq("user_id",userId);
        return userTeamService.remove(queryWrapper);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeByTeamId(Long id,User loginUser ) {
        if (loginUser == null){
            throw new BusinessException(ErrorCode.NOT_LOGIN,"请先登录！");
        }
        Team team = getById(id);
        if (team == null){
            throw  new BusinessException(ErrorCode.NOT_EXIST_DATA,"队伍不存在");
        }
        if (!loginUser.getId().equals(team.getUserId())){
            throw new BusinessException(ErrorCode.NO_AUTH, "无访问权限");
        }
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("team_id",id);
        boolean removeRow = userTeamService.remove(queryWrapper);
        if (!removeRow){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"解散队伍失败");
        }
        return removeById(id);
    }

    @Override
    public List<TeamVO> listMyTeam(User loginUser) {
        if (ObjectUtils.isEmpty(loginUser)){
            throw new BusinessException(ErrorCode.NOT_LOGIN);
        }
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",loginUser.getId());
        queryWrapper.select("team_id");
        List<Long> collect = userTeamService.list(queryWrapper).stream().map(UserTeam::getTeamId).collect(Collectors.toList());
        TeamQueryRequest queryRequest = new TeamQueryRequest();
        queryRequest.setIds(collect);
        return listTeam(queryRequest, userService.isAdmin(loginUser));
    }
}




